//此处实现的可执行程序就是CGI程序
# include<stdio.h>
# include<stdlib.h>
# include<unistd.h>
# include<string.h>
//分get和post两种情况计算的参数
//1、get从query_string中读取
//2、post从body中读取
//【通过分支条件把get和post请求的数据都放在buf这个缓冲区里面
//这段代码写完之后，不用去管get或者是post，直接去解析缓冲区中里面的数据，
//分get和post两种情况去处理数据。处理数据的情况还是按照cgi的方式来处理
//get请求用来计算的依据都在query_string里面，不需要使用管道。query_string是通过化境变量传递过来的
//对于get方法可以直接把环境变量拿到，并且把环境变量里面的内容拷贝到query_string里面
//获取输出参数，读取的结果就放在buf这个输出缓冲区中
//对于POST请求body部分才是要计算的依据，body部分必须读取管道，读取管道之前要先获取到
//content_length,管道里面的数据有多长，再根据长度进行循环，把body中的数据放到buf中。
static int GetQueryString(char buf[])
{
    //1、从环境变量中获取到方法是什么
    char* method=getenv("REQUEST_METHOD");
    //环境变量不存在时，method会是一个空指针
    if(NULL==method){
        //由于当前的CGI程序对用的输出已经被重定向到管道上了，
        //而这部分数据又会被返回给客户端，避免让程序内部的错误暴露给普通用户，通过stderr
        //来作为输出日志的手段
        fprintf(stderr,"[CGI] method==NULL\n");
        /*
        printf("error\n");
        //printf是往标准输出打印，重定向到管道里面，由父进程循环读取，并且从管道写入socket
        //把字符串输出到了客户端上；把内部的错误会报给客户所以不使用printf，而是使用
        //fprintf把错误输出到stderr上，对应2号文件描述符；只有0和1号文件描述符重定向了，
        //2号文件描述符没有重定向。此时输出的结果在文本上
        */
        return -1;
    }
    //2、判定方法是get还是post
    //如果是get，就从环境变量里面读取QUERY_STRING
    //如果是post，就从环境变量里读取CONTENT_LENGTH
   // char buf[1024*10]={0};
    //无论是get方法还是post方法都同一放到缓冲区里
    if(strcasecmp(method,"GET")==0){
        char *query_string=getenv("QUERY_STRING");
        if(query_string==NULL){
            fprintf(stderr,"[CGI] query_string is NULL\n");
            return -1;
        }
        //拷贝完成之后，buf里面的内容形如
        //a=10&b=20
        strcpy(buf,query_string);
    }
    else{
        char *content_length_str=getenv("CONTENT_LENGTH");
        if(content_length_str==NULL){
        fprintf(stderr,"[CGI] content_length is NULL\n");
        return -1;
        }
        int content_length=atoi(content_length_str);
        //把conten_length_str转化为整数
        int i=0;
        for(;i<content_length;++i){
            //从0号进程读，即读管道，读到了父进程写到管道里的
            //此处由于父进程把body已经写到管道，
            //子进程有已经把0号文件描述符重定向到了管道
            //此时从标准输入来读数据，也就读到了管道中的数据
            read(0,&buf[i],1);
        }
        //次循环读完之后，buf里面的内容就形如
        buf[i]='\0';
    }

    return 0;
}
